# amplitude.string -- string functions, work with both unicode and ascii strings.

import re
import amplitude.string    # needed w/in String class

class String(unicode):
    """our own unicode string class that adds several useful methods"""
    def camelify(self, title=True):
        return String(amplitude.string.camelify(self, title=title))
    def titleify(self, allwords=False, lastword=True, camelsplit=True):
        return String(amplitude.string.titleify(self, allwords=allwords, lastword=lastword, camelsplit=camelsplit))
    def identifier(self, lowercase=True):
        return String(amplitude.string.identifier(self, lowercase=lowercase))
    def nameify(self, allwords=False):
        return String(amplitude.string.nameify(self, allwords=allwords))
    def hyphenify(self, camelsplit=True):
        return String(amplitude.string.hyphenify(self, camelsplit=camelsplit))
    def camel_split(self):
        return String(amplitude.string.camel_split(self))
    def words(self):
        return String(amplitude.string.words(self))
    @classmethod
    def to_unicode(cls, s):
        return String(amplitude.string.to_unicode(s))
    def __add__(self, other):
        return String(unicode(self) + unicode(other))

def camelify(instring, title=True):
    """takes a string with spaces, hyphens, periods, and underscores and turns it into CamelCase"""
    outstring = instring
    if title==True:
        outstring = titleify(outstring, allwords=True)
    outstring = outstring.replace("&amp;", " ")
    outstring = re.sub("\W+", '', outstring, re.U)
    return outstring

# articles, conjunctions, prepositions, the s in 's
LOWERCASE_WORDS = "a an the and or nor for but than because vs to in on off from at of by under over through with against about across aboard above according after along alongside amid among apart around beneath beyond below beside behind before between concerning despite during into near onto throughout toward until unto upon versus via within without s amp n v adj adv prep ed ing eth th".split()

def titleify(instring, allwords=False, lastword=True, camelsplit=True):
    """takes a string and makes a title from it"""
    outstring = instring
    if camelsplit==True: outstring = camel_split(outstring)
    l = re.split("(\W+)", outstring.strip().replace("_", " "))
    for i in range(len(l)):
        l[i] = l[i].lower()
        if allwords==True or i == 0 or (lastword==True and i == len(l)-1) or l[i].lower() not in LOWERCASE_WORDS:
            w = l[i]
            if len(w) > 1:
                w = w[0].upper() + w[1:]
            else:
                w = w.upper()
            l[i] = w
    outstring = "".join(l)    
    return outstring

def identifier(instring, lowercase=True):
    id = nameify(instring).replace('-', '_')
    if lowercase==True: id = id.lower()
    return id    
    
def nameify(instring, allwords=False):
    """takes a title or camel string and makes a Title-with-Hyphens-to-Be-a-Name-or-Id-Attribute"""
    return hyphenify(titleify(camel_split(instring), allwords=allwords), 
                    camelsplit=False)
    
def hyphenify(instring, camelsplit=True):
    """takes a title or other string and turns non-word characters into single hyphens"""
    outstring = unicode(instring)
    if camelsplit==True:
        outstring = camel_split(outstring)
    outstring = re.sub('(?![A-Z])([A-Z])', r' \1', outstring).strip()
    outstring = outstring.replace("&amp;", " ")
    outstring = re.sub(u"""['"\u2018\u2019\u201c\u201d]""", '', outstring)
    outstring = re.sub("\W+", '-', outstring).strip(' -')
    return outstring

def camel_split(instring):
    outstring = instring
    for i in range(len(outstring)-1, -1, -1):
        if outstring[i].isupper() and i != 0 \
        and outstring[i-1].isalnum() and not outstring[i-1].isupper():
            outstring = outstring[:i] + ' ' + outstring[i:]
    return outstring
    
def to_unicode(instring):
    if type(instring) == unicode:
        outstring = instring
    elif type(instring) == str:
        outstring = unicode(instring, encoding='UTF-8')
    else:
        outstring = unicode(instring)
    return outstring
    
def words(instring):
    if type(instring) is None: return 0
    l = re.split(r"\s+", instring)
    return len(l)

